/**
BashNBump.cpp
Title: Bash 'N' Bump
Descr: A simple platform game.

Copyright (c) 2010, Brant Ryan Anderson
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <ORGANIZATION> nor the names of its contributors
      may be used to endorse or promote products derived from this software
      without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**/

#include "BashNBump.h"
#include "binge/utilities/Texture.h"
#include "system/BlockData.h"
GO_BINGE_GO(BashNBump);

// Level
binge::Texture* blockTex;
binge::Texture* pipeLeftTex;
binge::Texture* pipeRightTex;

// Characters
binge::Texture* peachKatTex;

// Player
int playerId;

sf::Font font;
sf::String benchText;
/*
sf::String livesText;
sf::String levelText;
sf::String scoreText;
*/
int lives;
int level;
int score;

BlockData block;

bool // Called before the engine has been initialized.
BashNBump::Preload(void)
{
    engine->SetGameTitle("Bash 'N' Bump");
    engine->SetFullscreen(false);
    engine->SetScreenWidth(800);
    engine->SetScreenHeight(600);
    engine->SetColorDepth(32);

    return true;
}

bool // Called after the engine has been initialized.
BashNBump::Init(void)
{
    lives = 3;
    level = 1;
    score = 0;

    if(!font.LoadFromFile("FreeSerif.ttf", 20))
    {
        return false;
    }

    benchText.SetFont(font);
    benchText.SetColor(sf::Color(255, 255, 255));
    benchText.SetPosition(96.f, 12.f);
    benchText.SetSize(20);

    /*
    livesText.SetFont(font);
    livesText.SetColor(sf::Color(255, 255, 255));
    livesText.SetPosition(96.f, 12.f);
    livesText.SetSize(20);

    levelText.SetFont(font);
    levelText.SetColor(sf::Color(255, 255, 255));
    levelText.SetPosition(336.f, 12.f);
    levelText.SetSize(20);

    scoreText.SetFont(font);
    scoreText.SetColor(sf::Color(255, 255, 255));
    scoreText.SetPosition(576.f, 12.f);
    scoreText.SetSize(20);
    */

    LoadLevel();

    return true;
}

void // Called from the main game loop at max fps.
BashNBump::HandleInput(sf::Event ev)
{
    static bool up_IsPressed = false;
    static bool left_IsPressed = false;
    static bool right_IsPressed = false;

    if( ev.Type == sf::Event::KeyPressed )
    {
        if(ev.Key.Code == sf::Key::Escape)
        {
            engine->Shutdown();
        }
        if(ev.Key.Code == sf::Key::Up)
        {
            if(!up_IsPressed)
            {
                up_IsPressed = true;
                PressJump();
            }
        }
        if(ev.Key.Code == sf::Key::Left)
        {
            if(!left_IsPressed)
            {
                left_IsPressed = true;
                PressLeft();
            }
        }
        if(ev.Key.Code == sf::Key::Right)
        {
            if(!right_IsPressed)
            {
                right_IsPressed = true;
                PressRight();
            }
        }
    }
    if( ev.Type == sf::Event::KeyReleased )
    {
        if(ev.Key.Code == sf::Key::Up)
        {
            up_IsPressed = false;
            ReleaseJump();
        }
        if(ev.Key.Code == sf::Key::Left)
        {
            left_IsPressed = false;
            ReleaseLeft();
        }
        if(ev.Key.Code == sf::Key::Right)
        {
            right_IsPressed = false;
            ReleaseRight();
        }
    }
}

void // Called for updating game data at max fps.
BashNBump::Update(void)
{

    std::ostringstream sBench;
    sBench << "Core Rate: " << engine->GetFrameRate_core();
    sBench << "            ";
    sBench << "Frame Rate: " << engine->GetFrameRate_real();
    benchText.SetText(sBench.str());

/*
    std::ostringstream sLives;
    sLives << "Lives: " << lives;
    livesText.SetText(sLives.str());

    std::ostringstream sLevel;
    sLevel << "Level: " << level;
    levelText.SetText(sLevel.str());

    std::ostringstream sScore;
    sScore << "Score: " << score;
    scoreText.SetText(sScore.str());
*/
}

void // Called for rendering at 60 fps.
BashNBump::Render(void)
{
    engine->screen.Draw(benchText);
/*
    engine->screen.Draw(livesText);
    engine->screen.Draw(levelText);
    engine->screen.Draw(scoreText);
*/
}

void // Called when a Game Object has moved.
BashNBump::GOBMoved(int objId)
{
    AnimateBlocks();

    if (objId == playerId)
    {
        if (engine->gravity.GetStatus(objId) == binge::GRAVITY_WALKING)
        {
            if (engine->animation.GetName(playerId) == "JUMP_RIGHT")
            {
                if (engine->movement.GetXVelocity(objId) > 0)
                {
                    engine->animation.SetName(objId, "MOVE_RIGHT");
                }
                else
                {
                    engine->animation.SetName(objId, "STAND_RIGHT");
                }
            }
            else if (engine->animation.GetName(playerId) == "JUMP_LEFT")
            {
                if (engine->movement.GetXVelocity(objId) < 0)
                {
                    engine->animation.SetName(objId, "MOVE_LEFT");
                }
                else
                {
                    engine->animation.SetName(objId, "STAND_LEFT");
                }
            }
        }
        // Keep the player in bounds.
        float xpos = engine->position.GetX(objId);
        if (xpos < 0 || xpos > 768)
        {
            engine->movement.SetXVelocity(objId, 0.f);
        }
    }

    if (objId != playerId)
    {
        if (engine->movement.GetXVelocity(objId) < 0)
        {
            engine->animation.SetName(objId, "MOVE_LEFT");
        }
        else if (engine->movement.GetXVelocity(objId) > 0)
        {
            engine->animation.SetName(objId, "MOVE_RIGHT");
        }
        if (engine->position.GetY(objId) > engine->GetScreenHeight())
        {
            engine->gameObjects.SetAlive(objId, false);
        }
    }
}

void
BashNBump::GOBRendered(int objId)
{

}

void
BashNBump::GOBCollision(int objId1, int objId2, int sides)
{

}

void
BashNBump::TileCollision(int objId, int tileId, int side)
{
    if (objId == playerId && side == binge::COLLISION_BOTTOM && block.Has(tileId))
    {
        block.SetHit(tileId, true);
        block.SetMoving(tileId, true);
    }

    if (objId != playerId && side == binge::COLLISION_TOP && block.Has(tileId))
    {
        if (block.IsHit(tileId))
        {
            engine->movement.SetXVelocity(objId, 0.f);
            engine->collision.RemoveObject(objId);
        }
    }
}

void
BashNBump::GOBRemoved(int objId)
{

}

void // Called when the game exits the main game loop.
BashNBump::End(void)
{
    // Level
    if (blockTex) delete blockTex;
    if (pipeLeftTex) delete pipeLeftTex;
    if (pipeRightTex) delete pipeRightTex;

    // Characters
    if (peachKatTex) delete peachKatTex;
}

// PUT USER DEFINED METHODS BELOW HERE
void
BashNBump::PressJump(void)
{
    if (engine->gravity.GetStatus(playerId) == binge::GRAVITY_WALKING)
    {
        if (engine->animation.GetName(playerId) == "MOVE_RIGHT"
            || engine->animation.GetName(playerId) == "STAND_RIGHT")
        {
            engine->animation.SetName(playerId, "JUMP_RIGHT");
        }
        if (engine->animation.GetName(playerId) == "MOVE_LEFT"
            || engine->animation.GetName(playerId) == "STAND_LEFT")
        {
            engine->animation.SetName(playerId, "JUMP_LEFT");
        }
        engine->gravity.SetStatus(playerId, binge::GRAVITY_JUMPING);
    }
}

void
BashNBump::ReleaseJump(void)
{
    if (engine->gravity.GetStatus(playerId) == binge::GRAVITY_JUMPING)
    {
        engine->gravity.SetStatus(playerId, binge::GRAVITY_FALLING);
    }
}

void
BashNBump::PressLeft(void)
{
    engine->animation.SetName(playerId, "MOVE_LEFT");

    // Keep the player in bounds.
    float xpos = engine->position.GetX(playerId);
    if (xpos < 0)
    {
        engine->movement.SetXVelocity(playerId, 0.f);
    }
    else
    {
        engine->movement.SetXVelocity(playerId, -3.f);
    }
}

void
BashNBump::ReleaseLeft(void)
{
    engine->movement.SetXVelocity(playerId, 0.f);
    engine->animation.SetName(playerId, "STAND_LEFT");
}

void
BashNBump::PressRight(void)
{
    engine->animation.SetName(playerId, "MOVE_RIGHT");

    // Keep the player in bounds.
    float xpos = engine->position.GetX(playerId);
    if (xpos > 768)
    {
        engine->movement.SetXVelocity(playerId, 0.f);
    }
    else
    {
        engine->movement.SetXVelocity(playerId, 3.f);
    }
}

void
BashNBump::ReleaseRight(void)
{
    engine->movement.SetXVelocity(playerId, 0.f);
    engine->animation.SetName(playerId, "STAND_RIGHT");
}

void
BashNBump::LoadLevel(void)
{
    int objId;

    blockTex = new binge::Texture;
    blockTex->Load("gfx/block.png");

    pipeLeftTex = new binge::Texture;
    pipeLeftTex->Load("gfx/pipe_left.png");

    pipeRightTex = new binge::Texture;
    pipeRightTex->Load("gfx/pipe_right.png");

    peachKatTex = new binge::Texture;
    peachKatTex->Load("gfx/peachkat.png");

    ////
    // BLOCKS
    // Left Column
    for (int y = 4; y < 21; y++)
    {
        int yoffset = y * 24.f;
        objId = engine->gameObjects.CreateObject("Left Column");
        engine->position.AddObject(objId);
        engine->position.SetPosition(objId, 0.f, yoffset);
        engine->render.AddObject(objId);
        engine->render.SetTexture(objId, blockTex);
        engine->collision.AddObject(objId);
        engine->collision.SetTile(objId, true);
        engine->collision.SetLeft(objId, 0.f);
        engine->collision.SetTop(objId, yoffset);
        engine->collision.SetRight(objId, 32.f);
        engine->collision.SetBottom(objId, yoffset+24.f);
    }
    objId = engine->gameObjects.CreateObject("Tile");
    engine->position.AddObject(objId);
    engine->position.SetPosition(objId, 0.f, 576.f);
    engine->render.AddObject(objId);
    engine->render.SetTexture(objId, blockTex);
    engine->collision.AddObject(objId);
    engine->collision.SetTile(objId, true);
    engine->collision.SetLeft(objId, 0.f);
    engine->collision.SetTop(objId, 576.f);
    engine->collision.SetRight(objId, 32.f);
    engine->collision.SetBottom(objId, 600.f);
    // Right Column
    for (int y = 4; y < 25; y++)
    {
        int yoffset = y * 24.f;
        objId = engine->gameObjects.CreateObject("Right Column");
        engine->position.AddObject(objId);
        engine->position.SetPosition(objId, 768.f, yoffset);
        engine->render.AddObject(objId);
        engine->render.SetTexture(objId, blockTex);
        engine->collision.AddObject(objId);
        engine->collision.SetTile(objId, true);
        engine->collision.SetLeft(objId, 768.f);
        engine->collision.SetTop(objId, yoffset);
        engine->collision.SetRight(objId, 800.f);
        engine->collision.SetBottom(objId, yoffset+24.f);
    }
    // First Row
    objId = engine->gameObjects.CreateObject("Tile");
    engine->position.AddObject(objId);
    engine->position.SetPosition(objId, 32.f, 96.f);
    engine->render.AddObject(objId);
    engine->render.SetTexture(objId, blockTex);
    engine->collision.AddObject(objId);
    engine->collision.SetTile(objId, true);
    engine->collision.SetLeft(objId, 32.f);
    engine->collision.SetTop(objId, 96.f);
    engine->collision.SetRight(objId, 32.f+32.f);
    engine->collision.SetBottom(objId, 120.f);

    objId = engine->gameObjects.CreateObject("Tile");
    engine->position.AddObject(objId);
    engine->position.SetPosition(objId, 736.f, 96.f);
    engine->render.AddObject(objId);
    engine->render.SetTexture(objId, blockTex);
    engine->collision.AddObject(objId);
    engine->collision.SetTile(objId, true);
    engine->collision.SetLeft(objId, 736.f);
    engine->collision.SetTop(objId, 96.f);
    engine->collision.SetRight(objId, 736.f+32.f);
    engine->collision.SetBottom(objId, 120.f);
    // Blocks
    for (int x = 2; x < 9; x++)
    {
        int xoffset = x * 32.f;
        objId = engine->gameObjects.CreateObject("Block");
        engine->position.AddObject(objId);
        engine->position.SetPosition(objId, xoffset, 96.f);
        engine->render.AddObject(objId);
        engine->render.SetTexture(objId, blockTex);
        engine->collision.AddObject(objId);
        engine->collision.SetTile(objId, true);
        engine->collision.SetLeft(objId, xoffset);
        engine->collision.SetTop(objId, 96.f);
        engine->collision.SetRight(objId, xoffset+32.f);
        engine->collision.SetBottom(objId, 120.f);
        block.AddObject(objId);
    }
    for (int x = 16; x < 23; x++)
    {
        int xoffset = x * 32.f;
        objId = engine->gameObjects.CreateObject("Block");
        engine->position.AddObject(objId);
        engine->position.SetPosition(objId, xoffset, 96.f);
        engine->render.AddObject(objId);
        engine->render.SetTexture(objId, blockTex);
        engine->collision.AddObject(objId);
        engine->collision.SetTile(objId, true);
        engine->collision.SetLeft(objId, xoffset);
        engine->collision.SetTop(objId, 96.f);
        engine->collision.SetRight(objId, xoffset+32.f);
        engine->collision.SetBottom(objId, 120.f);
        block.AddObject(objId);
    }
    // Second Row
    // Blocks
    for (int x = 7; x < 24; x++)
    {
        int xoffset = x * 32.f;
        objId = engine->gameObjects.CreateObject("Block");
        engine->position.AddObject(objId);
        engine->position.SetPosition(objId, xoffset, 192.f);
        engine->render.AddObject(objId);
        engine->render.SetTexture(objId, blockTex);
        engine->collision.AddObject(objId);
        engine->collision.SetTile(objId, true);
        engine->collision.SetLeft(objId, xoffset);
        engine->collision.SetTop(objId, 192.f);
        engine->collision.SetRight(objId, xoffset+32.f);
        engine->collision.SetBottom(objId, 216.f);
        block.AddObject(objId);
    }
    // Third Row
    // Blocks
    for (int x = 1; x < 18; x++)
    {
        int xoffset = x * 32.f;
        objId = engine->gameObjects.CreateObject("Block");
        engine->position.AddObject(objId);
        engine->position.SetPosition(objId, xoffset, 288.f);
        engine->render.AddObject(objId);
        engine->render.SetTexture(objId, blockTex);
        engine->collision.AddObject(objId);
        engine->collision.SetTile(objId, true);
        engine->collision.SetLeft(objId, xoffset);
        engine->collision.SetTop(objId, 288.f);
        engine->collision.SetRight(objId, xoffset+32.f);
        engine->collision.SetBottom(objId, 312.f);
        block.AddObject(objId);
    }
    // Fourth Row
    //Blocks
    for (int x = 7; x < 24; x++)
    {
        int xoffset = x * 32.f;
        objId = engine->gameObjects.CreateObject("Block");
        engine->position.AddObject(objId);
        engine->position.SetPosition(objId, xoffset, 384.f);
        engine->render.AddObject(objId);
        engine->render.SetTexture(objId, blockTex);
        engine->collision.AddObject(objId);
        engine->collision.SetTile(objId, true);
        engine->collision.SetLeft(objId, xoffset);
        engine->collision.SetTop(objId, 384.f);
        engine->collision.SetRight(objId, xoffset+32.f);
        engine->collision.SetBottom(objId, 408.f);
        block.AddObject(objId);
    }
    // Fifth Row
    objId = engine->gameObjects.CreateObject("Tile");
    engine->position.AddObject(objId);
    engine->position.SetPosition(objId, 32.f, 480.f);
    engine->render.AddObject(objId);
    engine->render.SetTexture(objId, blockTex);
    engine->collision.AddObject(objId);
    engine->collision.SetTile(objId, true);
    engine->collision.SetLeft(objId, 32.f);
    engine->collision.SetTop(objId, 480.f);
    engine->collision.SetRight(objId, 32.f+32.f);
    engine->collision.SetBottom(objId, 504.f);
    // Blocks
    for (int x = 2; x < 18; x++)
    {
        int xoffset = x * 32.f;
        objId = engine->gameObjects.CreateObject("Block");
        engine->position.AddObject(objId);
        engine->position.SetPosition(objId, xoffset, 480.f);
        engine->render.AddObject(objId);
        engine->render.SetTexture(objId, blockTex);
        engine->collision.AddObject(objId);
        engine->collision.SetTile(objId, true);
        engine->collision.SetLeft(objId, xoffset);
        engine->collision.SetTop(objId, 480.f);
        engine->collision.SetRight(objId, xoffset+32.f);
        engine->collision.SetBottom(objId, 504.f);
        block.AddObject(objId);
    }
    // Bottom Row
    for (int x = 1; x < 24; x++)
    {
        int xoffset = x * 32.f;
        objId = engine->gameObjects.CreateObject("Tile");
        engine->position.AddObject(objId);
        engine->position.SetPosition(objId, xoffset, 576.f);
        engine->render.AddObject(objId);
        engine->render.SetTexture(objId, blockTex);
        engine->collision.AddObject(objId);
        engine->collision.SetTile(objId, true);
        engine->collision.SetLeft(objId, xoffset);
        engine->collision.SetTop(objId, 576.f);
        engine->collision.SetRight(objId, xoffset+32.f);
        engine->collision.SetBottom(objId, 600.f);
    }
    // BLOCKS
    ////

    ////
    // PIPES
    // Top Left Pipe
    objId = engine->gameObjects.CreateObject("Left Pipe");
    engine->position.AddObject(objId);
    engine->position.SetPosition(objId, 0.f, 24.f);
    engine->render.AddObject(objId);
    engine->render.SetTexture(objId, pipeLeftTex);
    engine->collision.AddObject(objId);
    engine->collision.SetTile(objId, true);
    engine->collision.SetLeft(objId, 0.f);
    engine->collision.SetTop(objId, 24.f);
    engine->collision.SetRight(objId, 64.f);
    engine->collision.SetBottom(objId, 72.f);
    // Top Right Pipe
    objId = engine->gameObjects.CreateObject("Right Pipe");
    engine->position.AddObject(objId);
    engine->position.SetPosition(objId, 736.f, 24.f);
    engine->render.AddObject(objId);
    engine->render.SetTexture(objId, pipeRightTex);
    engine->collision.AddObject(objId);
    engine->collision.SetTile(objId, true);
    engine->collision.SetLeft(objId, 736.f);
    engine->collision.SetTop(objId, 24.f);
    engine->collision.SetRight(objId, 800.f);
    engine->collision.SetBottom(objId, 72.f);
    // Bottom Pipe
    objId = engine->gameObjects.CreateObject("Bottom Pipe");
    engine->position.AddObject(objId);
    engine->position.SetPosition(objId, 0.f, 504.f);
    engine->render.AddObject(objId);
    engine->render.SetTexture(objId, pipeLeftTex);
    engine->collision.AddObject(objId);
    engine->collision.SetTile(objId, true);
    engine->collision.SetLeft(objId, 0.f);
    engine->collision.SetTop(objId, 504.f);
    engine->collision.SetRight(objId, 64.f);
    engine->collision.SetBottom(objId, 576.f);
    // PIPES
    ////

    ////
    // PLAYER
    binge::AnimationSet rightAnimSet;
    std::vector<int> framesRight;
    framesRight.push_back(0);
    framesRight.push_back(1);
    framesRight.push_back(0);
    framesRight.push_back(2);
    rightAnimSet.SetFrames(framesRight);
    rightAnimSet.SetFrameTimer(160);
    rightAnimSet.SetName("MOVE_RIGHT");

    binge::AnimationSet rightStandAnimSet;
    std::vector<int> framesStandRight;
    framesStandRight.push_back(0);
    rightStandAnimSet.SetFrames(framesStandRight);
    rightStandAnimSet.SetFrameTimer(160);
    rightStandAnimSet.SetName("STAND_RIGHT");

    binge::AnimationSet rightJumpAnimSet;
    std::vector<int> framesJumpRight;
    framesJumpRight.push_back(3);
    rightJumpAnimSet.SetFrames(framesJumpRight);
    rightJumpAnimSet.SetFrameTimer(160);
    rightJumpAnimSet.SetName("JUMP_RIGHT");

    binge::AnimationSet leftAnimSet;
    std::vector<int> framesLeft;
    framesLeft.push_back(7);
    framesLeft.push_back(6);
    framesLeft.push_back(7);
    framesLeft.push_back(5);
    leftAnimSet.SetFrames(framesLeft);
    leftAnimSet.SetFrameTimer(160);
    leftAnimSet.SetName("MOVE_LEFT");

    binge::AnimationSet leftStandAnimSet;
    std::vector<int> framesStandLeft;
    framesStandLeft.push_back(7);
    leftStandAnimSet.SetFrames(framesStandLeft);
    leftStandAnimSet.SetFrameTimer(160);
    leftStandAnimSet.SetName("STAND_LEFT");

    binge::AnimationSet leftJumpAnimSet;
    std::vector<int> framesJumpLeft;
    framesJumpLeft.push_back(4);
    leftJumpAnimSet.SetFrames(framesJumpLeft);
    leftJumpAnimSet.SetFrameTimer(160);
    leftJumpAnimSet.SetName("JUMP_LEFT");

    playerId = engine->gameObjects.CreateObject("Bob");
    engine->position.AddObject(playerId);
    engine->position.SetPosition(playerId, 64.f, 528.f);
    engine->movement.AddObject(playerId);
    engine->animation.AddObject(playerId);
    engine->animation.SetColumns(playerId, 4);
    engine->animation.SetTotalFrames(playerId, 8);
    engine->animation.AddAnimSet(playerId, rightAnimSet);
    engine->animation.AddAnimSet(playerId, rightStandAnimSet);
    engine->animation.AddAnimSet(playerId, rightJumpAnimSet);
    engine->animation.AddAnimSet(playerId, leftAnimSet);
    engine->animation.AddAnimSet(playerId, leftStandAnimSet);
    engine->animation.AddAnimSet(playerId, leftJumpAnimSet);
    engine->animation.SetName(playerId, "STAND_RIGHT");
    engine->render.AddObject(playerId);
    engine->render.LoadImage(playerId, "gfx/bob_spritesheet.png");
    engine->collision.AddObject(playerId);
    engine->collision.SetLeft(playerId, 64.f+3.f); // XPos + Padding
    engine->collision.SetTop(playerId, 528.f+5.f); // YPos + Padding
    engine->collision.SetRight(playerId, 64.f+32.f-4.f); // XPos + Width - Padding
    engine->collision.SetBottom(playerId, 528.f+64.f-13.f); // YPos + Height - Padding
    engine->gravity.AddObject(playerId);
    engine->gravity.SetJumpPeak(playerId, 108);
    // PLAYER
    ////

    ////
    // BADDIES
    binge::AnimationSet rightAnimSetPeachKat;
    std::vector<int> framesRightPeachKat;
    framesRightPeachKat.push_back(4);
    framesRightPeachKat.push_back(5);
    framesRightPeachKat.push_back(6);
    rightAnimSetPeachKat.SetFrames(framesRightPeachKat);
    rightAnimSetPeachKat.SetFrameTimer(160);
    rightAnimSetPeachKat.SetName("MOVE_RIGHT");

    binge::AnimationSet leftAnimSetPeachKat;
    std::vector<int> framesLeftPeachKat;
    framesLeftPeachKat.push_back(0);
    framesLeftPeachKat.push_back(1);
    framesLeftPeachKat.push_back(2);
    leftAnimSetPeachKat.SetFrames(framesLeftPeachKat);
    leftAnimSetPeachKat.SetFrameTimer(160);
    leftAnimSetPeachKat.SetName("MOVE_LEFT");

    objId = engine->gameObjects.CreateObject("Peach Kat");
    engine->position.AddObject(objId);
    engine->position.SetPosition(objId, 704.f, 64.f);
    engine->movement.AddObject(objId);
    engine->movement.SetXVelocity(objId, -1.f);
    engine->animation.AddObject(objId);
    engine->animation.AddAnimSet(objId, rightAnimSetPeachKat);
    engine->animation.AddAnimSet(objId, leftAnimSetPeachKat);
    engine->animation.SetColumns(objId, 4);
    engine->animation.SetTotalFrames(objId, 8);
    engine->animation.SetName(objId, "MOVE_LEFT");
    engine->render.AddObject(objId);
    engine->render.SetTexture(objId, peachKatTex);
    engine->collision.AddObject(objId);
    engine->collision.SetLeft(objId, 704.f);
    engine->collision.SetTop(objId, 64.f);
    engine->collision.SetRight(objId, 704.f+32.f);
    engine->collision.SetBottom(objId, 64.f+32.f);
    engine->gravity.AddObject(objId);
    engine->gravity.SetXWallReflect(objId, true);
    // BADDIES
    ////
}

void
BashNBump::AnimateBlocks(void)
{
    for (int j = 0; j < block.GetCount(); j++)
    {
        int id = block.GetIdByIndex(j);
        if (engine->position.Has(id) && engine->collision.Has(id))
        {
            // Time based animation
            if (block.GetMoveTimer(id) > 0)
            {
                if (block.timer.GetTimer() > block.GetMoveStart(id) + block.GetMoveTimer(id))
                {
                    // Reset the Timer
                    block.SetMoveStart(id, block.timer.GetTimer());
                    // Animate Block
                    if (block.IsMoving(id))
                    {
                        if (block.IsHit(id))
                        {
                            if (block.GetMoveValue(id) > 10)
                            {
                                block.SetHit(id, false);
                            }
                            block.SetMoveValue(id, block.GetMoveValue(id)+2);
                            engine->position.SetY(id, engine->position.GetY(id)-2);
                            engine->collision.SetTop(id, engine->collision.GetTop(id)-2);
                            engine->collision.SetBottom(id, engine->collision.GetBottom(id)-2);
                        }
                        else
                        {
                            if (block.GetMoveValue(id) == 0)
                            {
                                block.SetMoving(id, false);
                            }
                            else
                            {
                                block.SetMoveValue(id, block.GetMoveValue(id)-2);
                                engine->position.SetY(id, engine->position.GetY(id)+2);
                                engine->collision.SetTop(id, engine->collision.GetTop(id)+2);
                                engine->collision.SetBottom(id, engine->collision.GetBottom(id)+2);
                            }
                        }
                    }
                }
            }
            else // No timing
            {
                // Animate Block
                if (block.IsMoving(id))
                {
                    if (block.IsHit(id))
                    {
                        if (block.GetMoveValue(id) > 10)
                        {
                            block.SetHit(id, false);
                        }
                        block.SetMoveValue(id, block.GetMoveValue(id)+2);
                        engine->position.SetY(id, engine->position.GetY(id)-2);
                        engine->collision.SetTop(id, engine->collision.GetTop(id)-2);
                        engine->collision.SetBottom(id, engine->collision.GetBottom(id)-2);
                    }
                    else
                    {
                        if (block.GetMoveValue(id) == 0)
                        {
                            block.SetMoving(id, false);
                        }
                        else
                        {
                            block.SetMoveValue(id, block.GetMoveValue(id)-2);
                            engine->position.SetY(id, engine->position.GetY(id)+2);
                            engine->collision.SetTop(id, engine->collision.GetTop(id)+2);
                            engine->collision.SetBottom(id, engine->collision.GetBottom(id)+2);
                        }
                    }
                }
            }
        }
    }
}
